/*************************************************************************
	> File Name: ./include/ConcurrentAlloc.h
	> Author: zq
	> Mail: zhouquan1511@163.com 
	> Created Time: Fri 28 Apr 2023 07:17:58 PM CST
 ************************************************************************/
#pragma once

#include "Common.h"
#include "ThreadCache.h"
#include "ObjectPool.h"

static void* ConcurrentAlloc(size_t size) {
	if (size > MAX_BYTES) {
		//大于256KB的申请，交给pageCache处理
		size_t alignBytes = SizeClass::RoundUp(size);
		size_t kPage = alignBytes >> PAGE_SHIFT;

		PageCache::GetInstance()->_pageMtx.lock();
		Span *span = PageCache::GetInstance()->NewSpan(kPage);
		span->_objSize = size;
		PageCache::GetInstance()->_pageMtx.unlock();
		
		void *ptr = (void*)(span->_pageId << PAGE_SHIFT);
		return ptr;
	}
	else {
		//小于等于256KB的申请，交给threadCache处理
		if (pTLSThreadCache == nullptr) {
			static std::mutex tcMtx;
			static ObjectPool<ThreadCache> tcPool;
			tcMtx.lock();
			pTLSThreadCache = tcPool.New();
			tcMtx.unlock();
		}
		return pTLSThreadCache->Allocate(size);
	}
}

static void ConcurrentFree(void *ptr) {
	Span *span = pageCache::GetInstance()->MapObjectToSpan(ptr);
	size_t size = span->objSize;
	if (size > MAX_BYTES) {
		//大于256kb的内存回收
		PageCache::GetInstance()->_pageMtx.lock();
		PageCache::GetInstance()->ReleaseSpanToPageCache(span);
		PageCache::GetInstance()->_pageMtx.unlock();
	}
	else {
		//小于等于256kb的内存回收
		assert(pTLSThreadCache);
		pTLSThreadCache->Deallocate(ptr, size);
	}
}
